<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- var 的作用域本质上是指变量/函数可供访问的范围。var可以在全局范围声明或函数/局部范围内声明。
当在最外层函数的外部声明var变量时，作用域是全局的。这意味着在最外层函数的外部用var声明的任何变量都可以在windows中使用。
当在函数中声明var时，作用域是局部的。这意味着它只能在函数内访问。 -->
    <script>
        console.log(num);  //undefined
        var num = 666;
        console.log(run);   //undefined
        var run = function () {
            console.log('run');
        }
        // console.log(run); //function
        run(); // run
        console.log("==="); // ===

        // var 可以重复声明(不推荐)

        /* console.log(a); //undefined
        var a = 10;
               a = 20;
        console.log(a);  //20 */
        // 有声明提升
        // 以函数区分作用域
        var num = 20;
        console.log(num);  // 20
        function run2() {
            console.log(num);  // undefined
            var num = 30;
            console.log(num);  // 30
            var n = 100;
        }
        run2();
        // console.log(n); ////报错 外部作用域不可以使用内部作用域的变量

        // let没有声明提升
        // let的作用域是以{}区分的 块级作用域
        // let不可以重复声明
        // console.log(str); 报错
        let str = "111";
        if (true) {
            let str1 = "222";
            console.log(str1); // 222
        }
        // console.log(str1); //报错
        // let str = "333";  //报错
        if (true) {
            var num3 = 40;
        }
        console.log(num3); //40
        // 同步: 代码从上往下一步一步执行,上面代码没有执行完,下边代码不会执行
        // 异步: 代码从上往下,可以让一下需要等待时间的代码同时执行,不影响下边代码的执行
        // 同步程序全部执行完才会执行异步
        // index是全局变量
        // 循环先执行; 操作的是唯一的一个index值的更改
        // 在循环执行完后,再次使用index 得到的是更改后的index的值
        // for循环是同步，setTimeout是异步
        for (var index = 0; index < 10; index++) {
            // console.log(index);
            // 异步执行
            setTimeout(function(){
            // 先进行等待，实际上程序是正常运行的，但是没有执行，等76行同步执行完之后才会执行的
                console.log(index);// （10）10
            },4)
        }
        console.log("------");
        console.log(index); //10

        // b是 块级变量
        // 会先执行循环, 但是每个循环都是一个单独的作用域(对于let来说)
        // 那么在每个循环体中都会有一个块级变量b的值等于当前b的值
        // 每个作用域都是独立的
        // 在循环内后来使用b时,得到的都是当前作用域记录的b的值
        for (let b = 2; b < 10 ; b++ ) {
            setTimeout(function() {
                console.log(b);   // 2--9
            }, 4);
        }
        // console.log("====",b); //报错
    </script>
    <!--let 是块级作用域,块是由 {} 界定的代码块，大括号中有一个块。大括号内的任何内容都包含在一个块级作用域中.
    因此，在带有let的块中声明的变量仅可在该块中使用,let 可以被修改但是不能被重新声明.。
    用var声明的变量会被提升到其作用域的顶部，并使用 undefined 值对其进行初始化。
    用let声明的变量会被提升到其作用域的顶部，不会对值进行初始化。 -->

    <!-- js常见的异步操作（个人理解需要耗时很长的操作）
1）setTimeout (setInterval)
2）AJAX
3）事件绑定(如：.on，.bind，.listen，.addEventListener，.observe)
4）观察者模式(例如：websocket中就有发布和订阅之类的操作)
5）promise 是一个异步操作，但是它是一个异步操作的解决方案，即保存着异步操作的结果，可以把异步函数以同步函数的形式写出来（Promise的成功|失败的回调（.then（）/.catch（））
6）async/await — 使用generator的语法糖，可以理解为是generator的一种改进
7）generator函数 — 使用promise的语法糖，可以理解为是promise的另一种拓展 -->
</body>

</html>